#include"Date.h"

//构造函数进行初始化
Date::Time::Time(int year, int month, int day, int week,int zodiac):_year(year),_month(month),_day(day),_week(week),_zodiac(zodiac)
{
	if (year == -1 && month == -1 && day == -1 && week == -1 && zodiac == -1)
	{
		long long t = 0;
		time(&t);
		t = (t / (3600)) - 24;
		_year = 1970, _month = 1, _day = 1, _week = 4, _zodiac = 11;
		while (t > 0)
		{
			if (_day == GetDay(_year, _month))
			{
				++_month;
				_day = 0;
				if (_month == 13)
				{
					++_year;
					++_zodiac;
					_month = 1;
					if (_zodiac == 13)
					{
						_zodiac = 1;
					}
				}
			}
			t -= 24;
			++_day;
			++_week;
			if (_week == 7)
			{
				_week = 0;
			}
		}
	}
}

//通过年月获取当月天数
int Date::Time::GetDay(int year, int month)
{
	if (month > 12 || month < 1)
	{
		cout << "输入不合法！" << endl;
		exit(EOF);
	}

	int day[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
	//闰年-2月有29天
	if (2 == month && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)))
	{
		return day[month] + 1;
	}

	return day[month];
}

ostream& Date::operator<<(ostream& out, const Date::Time& t)
{
	string week[] = { "日", "一",  "二",  "三",  "四",  "五",  "六", };
	string zodiac[] = {" ", "鼠", "牛",  "虎",  "兔",  "龙",  "蛇",  "马","羊" ,"猴" ,"鸡" ,"狗","猪" };
	cout << t._year << zodiac[t._zodiac] << "年 " <<t._month << "月" << t._day << "日 " << "星期" << week[t._week];
	return out;
}

//Date::Time& Date::Time::operator=(Time& t)
//{
//	_year = t._year;
//	_month = t._month;
//	_day = t._day;
//	_week = t._week;
//	return *this;
//}

//+=支持连+=
Date::Time& Date::Time::operator+=(int day)
{
	if (day > 0)
	{
		_week = (day + _week) % 7;
		_day += day;

		//月进位
		while (_day > GetDay(_year, _month))
		{
			_day -= GetDay(_year, _month);
			++_month;

			//年进位
			if (_month == 13)
			{
				++_year;
				++_zodiac;
				if (_zodiac == 13)
				{
					_zodiac = 1;
				}
				_month = 1;
			}
		}
	}
	else if (day < 0)
	{
		*this -= abs(day);
	}
	
	return *this;
}

//+支持连+
Date::Time Date::Time::operator+(int day)
{
	Time tmp(*this);
	tmp += day;
	return tmp;
}

Date::Time& Date::Time::operator-=(int day)
{
	if (day > 0)
	{
		if (_day < day)
		{
			if (_week == 0)
			{
				_week = 7;
			}
			--_month;
			//如果天数不够就减月
			while (day--)
			{
				_day -= 1;
				if (_day == 0)
				{
					//如果月不够取年
					if (_month == 0 && _year > 0)
					{
						_month = 12;
						--_year;
						--_zodiac;
						if (_zodiac == 0)
						{
							_zodiac = 12;
						}
					}
					else if (_year <= 0)
					{
						cout << "当前日期不合法！程序自动退出！" << endl;
						exit(EOF);
					}
					_day = GetDay(_year, _month);
					--_month;
				}
				_week -= 1;
				if (_week == 0)
				{
					_week = 7;
				}
			}
			//处理月份因为取月天数而错减的情况
			if (_month == 12)
			{
				++_year;
				++_zodiac;
				if (_zodiac == 13)
				{
					_zodiac = 1;
				}
				_month = 1;
			}
			else
			{
				++_month;
			}
		}
		else//小天数直接迭代找星期
		{
			int d = day;
			while (d)
			{
				if (_week == 0)
				{
					_week = 7;
				}
				--d;
				--_week;
			}
			_day -= day;
		}
		if (_week == 7)
		{
			_week = 0;
		}
	}
	else if (day < 0)
	{
		*this += abs(day);
	}
	return *this;
}

//-支持连-
Date::Time Date::Time::operator-(int day)
{
	Time tmp(*this);
	tmp -= day;
	return tmp;
}

//前置++天
Date::Time& Date::Time::operator++()
{
	*this += 1;
	return *this;
}

//后置++天
Date::Time Date::Time::operator++(int)
{
	Time tmp(*this);
	*this += 1;
	return tmp;
}

//前置--天
Date::Time& Date::Time::operator--()
{
	*this -= 1;
	return *this;
}

//后置--天
Date::Time Date::Time::operator--(int)
{
	Time tmp(*this);
	*this -= 1;
	return tmp;
}


//-支持连-  年-年得天数-相差多少天-效率较差
int Date::Time::operator-(const Date::Time& t)
{
	int num = 0;
	if (*this < t)
	{
		Time tmp(*this);
		while (tmp != t)
		{
			tmp += 1;
			++num;
		}
		return -num;
	}
	else if(*this > t)
	{
		Time tmp(t);
		while (*this != tmp)
		{
			tmp += 1;
			++num;
		}
	}
	return num;
}	


istream& Date::operator>>(istream& in, Time& t)
{
	int year = t._year, month = t._month, day = t._day;
	cout << "请输入年份:";
	cin >> t._year;
	cout << "请输入月份:";
	cin >> t._month;
	cout << "请输入天数:";
	cin >> t._day;
	if (year != t._year)
	{
		year -= t._year;
		//year获取修改前的年份，如果比今年小则是负数
		if (year > 0)
		{
			while (year--)
			{
				if (t._zodiac == 0)
				{
					t._zodiac = 12;
				}
				--(t._zodiac);
			}
		}
		else if (year < 0)
		{
			while (year++)
			{
				if (t._zodiac == 13)
				{
					t._zodiac = 1;
				}
				++(t._zodiac);
			}
		}
	}
	if (year != t._year || month != t._month)
	{
		t.GetWeekZodiac();
	}
	if (year == t._year || month == t._month && day != t._day)
	{
		day -= t._day;
		if (day > 0)
		{
			while (day--)
			{
				if (t._week == 0)
				{
					t._week = 7;
				}
				--(t._week);
			}
			if (t._week == 7)
			{
				t._week = 0;
			}
		}
		else if (day < 0)
		{
			while (day++)
			{
				if (t._week == 7)
				{
					t._week = 0;
				}
				++(t._week);
			}
			if (t._week == 7)
			{
				t._week = 0;
			}
		}
		

	}
	return in;
}

//根据时差获得星期-以今天的时间进行计算
int Date::Time::GetWeekZodiac()
{
	Time tmp;
	int day = *this - tmp;
	//对于以前的时间使用相减处理
	if (day <= 0)
	{
		while (day++)
		{
			if (this->_week == 0)
			{
				this->_week = 7;
			}
			--(this->_week);
		}
		if (this->_week == 7)
		{
			this->_week = 0;
		}
	}
	else if (day > 0)//对于增加的时间进行算法处理
	{
		this->_week = (day + tmp._week) % 7;
	}
	
	return this->_week;
}


bool Date::Time::operator==(const Date::Time& t) const
{
	return (_year == t._year && _month == t._month && _day == t._day);
}

bool Date::Time::operator<(const Date::Time& t) const
{
	return ((_year < t._year) ||
		(_year == t._year && _month < t._month) ||
		(_year == t._year && _month == t._month && _day < t._day));
}

bool Date::Time::operator<=(const Date::Time& t) const
{
	return (*this == t) || (*this < t);
}

bool Date::Time::operator>(const Date::Time& t) const
{
	return !(*this <= t);;
}

bool Date::Time::operator>=(const Date::Time& t) const
{
	return (*this == t) || !(*this < t);
}

bool Date::Time::operator!=(const Date::Time& t) const
{
	return !(*this == t);
}

void Date::Main::Menu()
{
	cout << "******************************" << endl;
	cout << "*       》日期计算器《       *" << endl;
	cout << "******************************" << endl;
	cout << "*         1.进入程序         *" << endl;
	cout << "*         0.退出程序         *" << endl;
	cout << "******************************" << endl;
	cout << "请选择>";
}

void Date::Main::Menu(Time& t)
{
	cout << "******************************" << endl;
	cout << "*    $日期计算器功能菜单$    *" << endl;
	cout << "******************************" << endl;
	cout << "*         !当前时间!         *" << endl;
	cout <<"*   " << t << "   *" << endl;
	cout << "******************************" << endl;
	cout << "*       1.设置日期时间       *" << endl;
	cout << "*     2.计算N天前后的日期    *" << endl;
	cout << "*     3.计算日期相隔天数     *" << endl;
	cout << "*     4.查询人生已过天数     *" << endl;
	cout << "*         0.退出程序         *" << endl;
	cout << "******************************" << endl;
	cout << "请选择>";
}

void Date::Main::DateCal()
{
	int day = 0;
	cout << "请输入天数(正数代表向后的天数，负数代表向前的天数): ";
	cin >> day;
	Time tmp;
	tmp += day;
	system("cls");
	cout << tmp;;
	cout << endl;
	system("pause");
}

void Date::Main::DateValCal(Time& t)
{
	int input = 0;
	cout << "自定义区间(1)以今天时间为一个区间(2)>";
	cin >> input;
	if (input == 1)
	{
		system("cls");
		cout << "请输入第一个区间时间！\n";
		Time tmp1,tmp2;
		cin>>tmp1;
		system("cls");
		cout << "请输入第二个区间时间！\n";
		cin>>tmp2;
		system("cls");
		cout<<tmp1;
		cout << "  与  ";
		cout << tmp2;
		cout << "  相差 ";
		int day = tmp2 - tmp1;
		cout << day << " 天 (负数表示以前的时间)" << endl;
		system("pause");
	}
	else if (input == 2)
	{
		system("cls");
		Time tmp;
		cout << "请输入计算的区间时间！\n";
		cin>>tmp;
		system("cls");
		cout<<t;
		cout << "  与  ";
		cout << tmp;
		cout << "  相差 ";
		cout << tmp - t << " 天 (负数表示以前的时间)" << endl;
		system("pause");
	}
}

void Date::Main::DaysLived(Time& t)
{
	system("cls");
	Time tmp;
	cout << "请输入您的生日!" << endl;
	cin>>tmp;
	system("cls");
	cout << "恭喜你已经在人生中努力了 " << t - tmp << " 天!" << endl;
	system("pause");
}

void Date::Main::ModeTime(Time& t)
{
	system("cls");
	cout << "(1)设置新时间(2)恢复默认时间请选择>";
	int input = -1;
	cin >> input;
	if (input == 1)
	{
		system("cls");
		cout << "请输入设置的时间！" << endl;
		cin>>t;
	}
	else if (input == 2)
	{
		Time tmp;
		t = tmp;
	}
}

void Date::Main::MainProgram()
{
	system("cls");
	int input = -1;
	Menu();
	cin >> input;
	if (input == 1)
	{
		Time t;
		while (input)
		{
			system("cls");
			Menu(t);
			cin >> input;
			switch (input)
			{

			case 0:
			{
				break;
			}
			case 1:
			{
				ModeTime(t);
				break;
			}
			case 2:
			{
				DateCal();
				break;
			}
			case 3:
			{
				DateValCal(t);
				break;
			}

			case 4:
			{
				DaysLived(t);
				break;
			}

			}
		}
	}
	
}

